import java.io.*;
import java.util.Scanner;

// IO流工厂接口
interface IOStreamFactory {
    InputStream createInputStream() throws IOException;
    OutputStream createOutputStream() throws IOException;
}

// 文件流工厂
class FileStreamFactory implements IOStreamFactory {
    private final String filePath;

    public FileStreamFactory(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public InputStream createInputStream() throws IOException {
        return new FileInputStream(filePath);
    }

    @Override
    public OutputStream createOutputStream() throws IOException {
        return new FileOutputStream(filePath);
    }
}

// 字节数组流工厂
class ByteArrayStreamFactory implements IOStreamFactory {
    private final byte[] data; // 用于输入流
    private final ByteArrayOutputStream outputStream; // 用于输出流

    public ByteArrayStreamFactory() {
        this.data = new byte[0]; // 默认空数组
        this.outputStream = new ByteArrayOutputStream();
    }

    public ByteArrayStreamFactory(byte[] data) {
        this.data = data;
        this.outputStream = new ByteArrayOutputStream();
    }

    @Override
    public InputStream createInputStream() throws IOException {
        return new ByteArrayInputStream(data);
    }

    @Override
    public OutputStream createOutputStream() throws IOException {
        return outputStream;
    }

    // 获取字节数组输出流的缓冲区内容
    public byte[] getOutputData() {
        return outputStream.toByteArray();
    }
}

public class IOStreamFactoryDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 测试文件流工厂
        System.out.println("测试文件流工厂：");
        System.out.print("请输入文件路径（如 D:\\test.txt）: ");
        String filePath = scanner.nextLine();
        IOStreamFactory fileFactory = new FileStreamFactory(filePath);

        // 写入文件
        try (OutputStream out = fileFactory.createOutputStream()) {
            String content = "这是文件流工厂写入的测试内容！";
            out.write(content.getBytes("UTF-8"));
            System.out.println("已写入文件: " + filePath);
        } catch (IOException e) {
            System.err.println("文件写入错误: " + e.getMessage());
        }

        // 读取文件
        try (InputStream in = fileFactory.createInputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead = in.read(buffer);
            if (bytesRead != -1) {
                System.out.println("从文件读取内容: " + new String(buffer, 0, bytesRead, "UTF-8"));
            } else {
                System.out.println("文件为空");
            }
        } catch (IOException e) {
            System.err.println("文件读取错误: " + e.getMessage());
        }

        // 测试字节数组流工厂
        System.out.println("\n测试字节数组流工厂：");
        String inputString = "这是字节数组流工厂的测试输入！";
        IOStreamFactory byteArrayFactory = new ByteArrayStreamFactory(inputString.getBytes());

        // 读取字节数组
        try (InputStream in = byteArrayFactory.createInputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead = in.read(buffer);
            if (bytesRead != -1) {
                System.out.println("从字节数组读取内容: " + new String(buffer, 0, bytesRead));
            }
        } catch (IOException e) {
            System.err.println("字节数组读取错误: " + e.getMessage());
        }

        // 写入字节数组
        try (OutputStream out = byteArrayFactory.createOutputStream()) {
            String content = "这是字节数组流工厂写入的内容！";
            out.write(content.getBytes());
            byte[] outputData = ((ByteArrayStreamFactory) byteArrayFactory).getOutputData();
            System.out.println("字节数组写入内容: " + new String(outputData));
        } catch (IOException e) {
            System.err.println("字节数组写入错误: " + e.getMessage());
        }

        scanner.close();

        // 讨论与问答
        // 1. 工厂模式如何简化IO流的创建和使用
        //   - 封装创建逻辑：客户端只需调用工厂方法，无需了解具体流的实现细节。
        //   - 统一接口：通过IOStreamFactory接口，统一不同类型流的创建方式。
        //   - 易于维护：修改或替换流实现只需更改工厂类，无需改动客户端代码。
        //   - 可配置性：通过参数（如文件路径或字节数组）灵活创建不同流。

        // 2. 工厂模式相比直接创建IO流对象的优势
        //   - 解耦：客户端代码不直接依赖具体流类（如FileInputStream），降低耦合。
        //   - 可扩展性：新增流类型（如SocketStreamFactory）只需实现新工厂类。
        //   - 错误管理：工厂类可集中处理流创建的异常，提高代码健壮性。
        //   - 复用性：工厂可缓存或重用流对象（如ByteArrayOutputStream）。

        // 3. 如何扩展设计以支持更多类型的IO流
        //   - 添加新工厂类：如SocketStreamFactory、PipedStreamFactory，继承IOStreamFactory。
        //   - 参数化工厂：通过工厂构造参数支持不同配置（如文件路径、URL、缓冲区大小）。
        //   - 抽象工厂模式：为不同流类别（如文件、网络、内存）定义子接口，扩展功能。
        //   - 使用配置或依赖注入：通过配置文件或框架（如Spring）动态选择工厂。
    }
}